import store from "@/store";
import { message } from "ant-design-vue";
import { nanoid } from "nanoid";
import { computed, nextTick, ref, createVNode } from "vue";
import { Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
// 封装的请求
import request from "@/common/utils/request";
// 工具函数
import { baseSubtitle } from '@/views/shotstack/MixedCutPlatforms/utools/template.js'

// 轮询分片组数量
export const chunkNum = 3;

// 获取配置文件, 判断对应路由需要加载的文件模块
const work_ai_config = computed(() => {
  // TODO 测试结束需注释
  return store?.state?.shotstack?.work_ai_config || {};
  // return {
  //   // shotstack_driver: "alionline",
  //   shotstack_driver: "1",
  // };
});

// 导入混剪数据 使用的标准 用于测算x位置的字体大小
export const import_fontSize = 18.6667;

// 标题的字体大小
export const import_title_fontSize = 32;

// 声音克隆消耗次数
export const VOICE_USE_NUM = 1

// 富文本 以及创意工具 文字转语音字数限制
export const max_text_length = 2000;

// 手机组件宽高
const phoneWidth = ref(360);
const phoneHeight = computed(() => {
  return work_ai_config.value?.shotstack_driver == "alionline" ? 700 : 640;
});

// 获取每一个小圆点的 ssml结构内容
export const getSsmlcontent = (nodes) => {
  // 获得本项的文本
  let text = "";
  const ssmlArr = nodes.map((ele) => {
    // console.log(ele, '每一项');
    const nodeType = ele?.type?.name || ele?.type;
    // 处理文本, 停顿, 数字读音, 修改发音, 取消诵读直接不做处理
    if (nodeType == "text") {
      text += ele.text;
      return ele.text;
    } else if (nodeType == "break") {
      return `<break time="${ele.attrs.time}"/>`;
    } else if (nodeType == "phoneme") {
      text += ele.attrs.text;
      return `<phoneme alphabet="py" ph="${ele.attrs.ph}">${ele.attrs.text}</phoneme>`;
    } else if (nodeType == "say-as") {
      text += ele.attrs.text;
      return `<say-as interpret-as="${ele.attrs["interpret-as"]}">${ele.attrs.text}</say-as>`;
    } else if (nodeType == "CancelRead") {
      text += ele.attrs.cancelReadText;
    } else if (nodeType == "hardBreak") {
      text += "\n";
    }
  });
  const ssml_join = ssmlArr.join("");
  const ssml = `<speak>${ssml_join}</speak>`;

  return {
    text,
    ssml,
    isEmpty: ssml_join.trim() == "" ? true : false,
  };
};

// 获得最大宽度
export const getTextWidthUsingCanvas = (
  text,
  fontSize,
  fontFamily = "Arial"
) => {
  // 获取粗略的文本宽度, 从而计算出大致的初始 x 距离
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  const font = `${fontSize}px ${fontFamily}`;
  context.font = font;
  // return context.measureText(text).width;
  const lines = text.split("\n");
  // 获取最大的宽度
  let maxWidth = 0;
  lines.forEach((line) => {
    const width = context.measureText(line).width;
    if (width > maxWidth) {
      maxWidth = width;
    }
  });
  return maxWidth;
};

// 处理富文本方法
const handleProcessingData = (data) => {
  // 正在编辑此项tts_config
  if (data.ele.tts_id == data.tts_id) {
    const subtitleData = data.jsonData.content.map((jsonItem) => {
      const findIndex = data.ele.subtitle.findIndex(
        (i) => i.subtitle_id == jsonItem?.attrs?.subId
      );
      // 正在编辑此项subtitle, 判断是否变化然后复用
      if (findIndex != -1) {
        // 如果此项富文本的内容不为空
        if (!!jsonItem.content) {
          const ssmlDtaa = getSsmlcontent(jsonItem.content);
          // 如果文本或者ssml有变化
          if (
            data.ele.subtitle[findIndex].text !== ssmlDtaa.text ||
            data.ele.subtitle[findIndex].ssml !== ssmlDtaa.ssml
          ) {
            // 去除此项的音频相关的信息
            console.log(
              "文本或者ssml有变化文本或者ssml有变化文本或者ssml有变化文本或者ssml有变化文本或者ssml有变化文本或者ssml有变化"
            );
            data.ele.subtitle[findIndex].audio_url = "";
            data.ele.subtitle[findIndex].media_id = "";
            data.ele.subtitle[findIndex].text = ssmlDtaa.text;
            data.ele.subtitle[findIndex].ssml = ssmlDtaa.ssml;
            data.ele.subtitle[findIndex].duration = "";
            data.ele.subtitle[findIndex].start_time = 0;
            data.ele.subtitle[findIndex].end_time = 0;
          } else {
            data.ele.subtitle[findIndex].text = ssmlDtaa.text;
            data.ele.subtitle[findIndex].ssml = ssmlDtaa.ssml;
            console.log(
              "无变化无变化无变化无变化无变化无变化无变化无变化无变化"
            );
          }
        } else {
          data.ele.subtitle[findIndex].audio_url = "";
          data.ele.subtitle[findIndex]?.media_id &&
            (data.ele.subtitle[findIndex].media_id = "");
          data.ele.subtitle[findIndex].duration = "";
          data.ele.subtitle[findIndex].text = "";
          data.ele.subtitle[findIndex].ssml = "<speak></speak>";
          data.ele.subtitle[findIndex].duration = "";
          data.ele.subtitle[findIndex].start_time = 0;
          data.ele.subtitle[findIndex].end_time = 0;
        }
        return JSON.parse(JSON.stringify(data.ele.subtitle[findIndex]));
      } else {
        // 没有找到编辑的 subtitle, 创建一个新的subtitle -- 一般情况是用户回车创建的小圆点
        console.log(
          "没有找到编辑的 subtitle, 创建一个新的subtitle没有找到编辑的 subtitle, 创建一个新的subtitle没有找到编辑的 subtitle, 创建一个新的subtitle没有找到编辑的 subtitle, 创建一个新的subtitle"
        );
        let templateItem = JSON.parse(JSON.stringify(data.ele.subtitle[0]));
        templateItem.subtitle_id = jsonItem?.attrs?.subId;
        // 编辑的此项富文本内容不为空
        if (!!jsonItem.content) {
          const ssmlDtaa = getSsmlcontent(jsonItem.content);
          templateItem.text = ssmlDtaa.text;
          templateItem.ssml = ssmlDtaa.ssml;
        } else {
          // 此项是空项
          templateItem.text = "";
          templateItem.ssml = "<speak></speak>";
        }
        templateItem.start_time = 0;
        templateItem.end_time = 0;
        templateItem.audio_url = "";
        templateItem.duration = 0;
        templateItem?.media_id && (templateItem.media_id = "");
        // 更新此项的x轴数据
        // const element = document.querySelector(".editor_content");
        // const fontSize = parseFloat(getComputedStyle(element)["font-size"]);
        // const newTextWidth = getTextWidthUsingCanvas(
        //   templateItem.text,
        //   fontSize,
        //   templateItem.font_family
        // );
        // const is_x =
        //   templateItem.showX - newTextWidth / 2 < 0
        //     ? 0
        //     : templateItem.showX - newTextWidth / 2;
        // console.log(is_x, "我是xxx的值");

        // // 修改此项的x轴数据
        // templateItem.x = is_x;
        // templateItem.x = is_x <= 2 ? 2 : is_x;
        return JSON.parse(JSON.stringify(templateItem));
      }
    });
    data.ele.subtitle = subtitleData;
    data.ele.ssmlContent = data.content;
    if (data.ele.tab_id == "audio") {
      const allText = data.ele.subtitle.map((i) => i.text).join("");
      if (allText) {
        // 每个字的平均时间
        const text_time = data.ele.duration / allText.length;
        data.ele.subtitle.forEach((i, index) => {
          const item_time = i.text.length * text_time;
          i.start_time = index == 0 ? 0 : data.ele.subtitle[index - 1].end_time;
          i.end_time = i.start_time + item_time;
          i.duration = item_time;
        });
      }
    }
  }
};

/**
 * 处理视频组富文本onUpdate
 * @param {
 * subTitle(混剪数据)
 * tts_id(当前富文本编辑的id)
 * jsonData(富文本数据)
 * content(富文本文本数据)
 * currentDrawerIndex(当前编辑的视频组下标)
 * } data
 */
export const handleRichTextUpdate = (data) => {
  data.subTitle[data.currentDrawerIndex].tts_config.forEach((ele) => {
    handleProcessingData({
      ...data,
      ele,
    });
  });
};

// 全局富文本处理
export const handleRichTextGlobalUpdate = (data) => {
  data.subTitle.configs.forEach((ele) => {
    // 编辑的是此项
    handleProcessingData({
      ...data,
      ele,
    });
  });
};

// 截取文本最后一个换行符
export const clearWrap = (text) => {
  // 判断文本是否以换行符结尾
  if (text.endsWith("\n")) {
    // 去除末尾的换行符
    return text.slice(0, -1);
  }
  // 如果文本不以换行符结尾，则返回原样
  return text;
};

// 计算可拖拽区域的宽高比例
export const calculateDraggableArea = (userWidth, userHeight) => {
  const containerWidth = phoneWidth.value;
  const containerHeight = phoneHeight.value;

  // 计算缩放比例，这次我们用容器宽高除以用户宽高，以获取缩小比例
  const widthScale = containerWidth / userWidth;
  const heightScale = containerHeight / userHeight;

  // 选择较小的缩放比例以保持内容比例
  const scale = Math.min(widthScale, heightScale);

  // 使用缩放后的用户输入宽高作为可拖拽区域的宽高
  // 这会确保无论用户输入的分辨率如何，可拖拽区域都不会超出容器
  const draggableWidth = userWidth * scale;
  const draggableHeight = userHeight * scale;

  // 返回计算结果，包括可拖拽区域的宽高和缩放比例
  return { draggableWidth, draggableHeight, scale, widthScale, heightScale };
};

// 请求回来数据后, 进行比例换算, 换算回手机展示的比例
/**
 *
 * @param {} height
 * @param {*} width
 * @returns
 */
export const resetXY = (height, width) => {
  // 已有的计算可拖拽区域
  const { widthScale, heightScale } = calculateDraggableArea(
    phoneWidth.value,
    phoneHeight.value
  );
  // 计算当前宽高与目标分辨率的比例
  const targetScaleWidth = width / phoneWidth.value;
  const targetScaleHeight = height / phoneHeight.value;
  // 计算最终应用于元素的缩放比例
  const scaleWidth = targetScaleWidth * widthScale;
  const scaleHeight = targetScaleHeight * widthScale;

  // 此处返回的是缩放比例倍率, x和y除以缩放比例即为回显的正确比例
  return {
    scaleWidth,
    scaleHeight,
  };
};

// 获得字体大小转换的比例
const scaleData = computed(() => {
  const { showHeight, showWidth } =
    work_ai_config.value?.shotstack_driver == "alionline"
      ? store.state.videoMixCut.VideoMashup
      : store.state.shotstack.VideoMashup;
  return resetXY(showHeight, showWidth);
});

// 处理字幕组, 配置应用到全部字幕组
export const applyallSubtitle = (params) => {
  const { subTitle, currentDrawerIndex, tab_id } = params;

  return new Promise(async(resolve, rej) => {
    console.log(subTitle, 'subTitle是啥啊啊');

    try {

      // 点击全部应用的 当前视频组
    const subTitleUseItem = subTitle.value[currentDrawerIndex.value.index]
  
    // try {
    let find;
    // 使用不同的数据做基础数据
    if (tab_id.value == "text") {
      find = subTitle.value[currentDrawerIndex.value.index].tts_config.find(
        (ele) => ele.tab_id == "text"
      );
    } else {
      find = subTitle.value[currentDrawerIndex.value.index].tts_config.find(
        (ele) => ele.tab_id == "audio"
      );
    }
    const {
      subtitle,
    } = JSON.parse(JSON.stringify(find));
  
    const {
      audio_url: sub_audio_url,
      duration: sub_duration,
      subtitle_id,
      start_time: sub_start_time,
      end_time: sub_end_time,
      showX,
      x,
      y,
      text,
      ssml,
      rightX,
      elements,
      media_id,
      ...subData
    } = JSON.parse(JSON.stringify(subtitle[0]));
  
    // const {id,material_list,name,sticker_config,text_config, tts_config, time_strategy,   } = subTitleUseItem
    const { effect_config, flower_random_config, flower_random_tts_config } = subTitleUseItem
    const configs = {effect_config, flower_random_config, flower_random_tts_config}
  
    subTitle.value.forEach((item, index) => {
  
      // 同步其余项的配置
      if (index != currentDrawerIndex.value.index) {
        Object.assign(item, JSON.parse(JSON.stringify(configs)))
      }
      // 只有相同类型的数据才会被修改

      item.tts_config.forEach((ele) => {
        if (ele.tab_id == tab_id.value) {
          ele.subtitle.forEach((i) => {
      
            // 字体大小发生变化, 并且存在文本, 需要重新计算x和y
            console.log(subData, '合并到一起的 subtitle数据');
            if (i.font_size != subData.font_size) {
              
              Object.assign(i, JSON.parse(JSON.stringify(subData)));
              const font_size = +i.font_size / scaleData.value.scaleWidth;
              const textWidth = getTextWidthUsingCanvas(
                i.text,
                font_size,
                i.font_family
              );
              i.x = i.showX - textWidth / 2;
              return;
            }
            Object.assign(i, JSON.parse(JSON.stringify(subData)));
          });
        }
      });
    });
   resolve(subTitle.value)
    } catch (error) {
      rej(subTitle.value)
    }
  })


  // } catch (error) {
  //   message.error("视频设置应用到全部镜头组失败!");
  //   return new Error(error);
  // }
};

// 处理音色配置 应用到全部字幕组
export const applyallVoice = (params) => {
  const { subTitle, currentDrawerIndex, tab_id } = params;

  return new Promise(async(resolve, rej) => {
    console.log(subTitle, 'subTitle是啥啊啊');

    try {

      // 点击全部应用的 当前视频组
    const subTitleUseItem = subTitle.value[currentDrawerIndex.value.index]
  
    // try {
    let find;
    // 使用不同的数据做基础数据
    if (tab_id.value == "text") {
      find = subTitle.value[currentDrawerIndex.value.index].tts_config.find(
        (ele) => ele.tab_id == "text"
      );
    } else {
      find = subTitle.value[currentDrawerIndex.value.index].tts_config.find(
        (ele) => ele.tab_id == "audio"
      );
    }
    const {
      // start_time,
      iccts,
      subtitle,
      audio_url,
      duration,
      end_time,
      tab_id: tts_tab_id,
      tts_id,
      ssmlContent,
      // start_time,
      // speed,
      // showVoice,
      // tone_id,
      // recommendSpeed,
      // volume,
      // emotion_intensity,
      // emotion_category,
      // category,
      // img,
      // name,
      // id,
      // voice_type,
      // showSubtitle,
      ...atherData
    } = JSON.parse(JSON.stringify(find));

      console.log(atherData, '作为模板的数据');
  
      subTitle.value.forEach((item, index) => {
      // 合并tts配置
      item.tts_config.forEach((ele) => {
        if (ele.tab_id == tab_id.value) {
          console.log(atherData, '合并到一起的tts数据');
          // 默认不合并
          let merge = false
          for (let key in atherData) {
            if (atherData[key] != ele[key]) {
              merge = true
              break
            }
          }

          if (merge) {
            Object.assign(ele, JSON.parse(JSON.stringify(atherData)));
            ele.subtitle.forEach((i) => {
              if (index != currentDrawerIndex.value.index) {
                // 判断配置是否是否有不同的地方, 如果有不同的地方 则替换 并且重新获取音频
                // 不是本项数据的话, 清空音频
                  const clearObj = {
                    audio_url: '',
                    duration: 0,
                    end_time: 0,
                  }
                Object.assign(i, clearObj)
              }
            });
          }
            // Object.assign(ele, JSON.parse(JSON.stringify(atherData)));
        }
      });
    });
      
    // 批量获取音频
   await getAudioFn({resource_data: subTitle})
   resolve(subTitle.value)
    } catch (error) {
      rej(subTitle.value)
    }
  })
};

// 处理文字标题, 配置应用到全部
export const applyallTitle = (params) => {
  const { state, currentDrawerIndex, activeTextarea } = params;
  const editIndex = state.value[currentDrawerIndex.value].text_config.findIndex(
    (ele) => ele.id == activeTextarea.value
  );

  // 当前高亮的项, 作为配置到所有的基础配置
  if (editIndex != -1) {
    const find = state.value[currentDrawerIndex.value].text_config[editIndex];
    const { text, id, x, y, height, width, showX, ...atherData } = JSON.parse(
      JSON.stringify(find)
    );
    state.value.forEach((item) => {
      item.text_config.forEach((ele) => {
        if (ele.font_size != atherData.font_size) {
          Object.assign(ele, atherData);
          const font_size = +ele.font_size / scaleData.value.scaleWidth;
          const textWidth = getTextWidthUsingCanvas(
            ele.text,
            font_size,
            ele.font_family
          );
          ele.x = ele.showX - textWidth / 2;
          return;
        }
        Object.assign(ele, atherData);
      });
    });

    return state.value;
  }
};

// 处理全局标题, 视频设置应用到全部标题组
export const applyallGlobalTitle = (params) => {
  const { state, activeTextarea, TitleArr } = params;

  // 获得当前高亮的 配置到全部的配置数据
  const findTarget = state.value.find((ele) => ele.id == activeTextarea.value);
  console.log(findTarget, "基础数据");
  console.log(TitleArr.value, "应该是全部数据");

  if (!!findTarget) {
    const { id, showX, text, height, width, x, y, ...atherData } = findTarget;

    TitleArr.value.forEach((ele) => {
      ele.data.forEach((item) => {
        if (item.font_size != atherData.font_size) {
          Object.assign(item, JSON.parse(JSON.stringify(atherData)));
          const font_size = +item.font_size / scaleData.value.scaleWidth;
          const textWidth = getTextWidthUsingCanvas(
            item.text,
            font_size,
            item.font_family
          );
          item.x = item.showX - textWidth / 2;
          return;
        }
        Object.assign(item, JSON.parse(JSON.stringify(atherData)));
      });
    });

    return {
      TitleArr,
      state,
    };
  }

  return null;
};

// 文本按照标点符号切割的方法
export function splitTextAndRemoveCommas(text) {
  // 使用正则表达式进行拆分，匹配句号、问号（包括大小写）、逗号和感叹号
  const sentences = text.split(/(?<=[。？！!,，])/i);

  // 遍历数组，去除每个元素中的逗号和句号
  const result = sentences.map((sentence) => sentence.replace(/[，,。]/g, ""));

  // 过滤掉可能的空字符串
  const textArr = result.filter(
    (sentence) => sentence.trim() != "" && sentence.trim() != "\n"
  );

  return textArr;
}

/**
 * 处理文案库单项 导入到混剪富文本(已处理全局的局部导入兼容, 通过type区分)
 * @param {
 * data:文案库选择的数据, subTitle:弹窗中缓存的vuex中的混剪数据, currentDrawerIndex:当前编辑的富文本项下标
 * props:使用的组件中传递的props数据, sizeData:组件中导入的对应尺寸数据,
 * current_tts_data: 当前编辑的此项数据, getContent:组件中的 将当前数据转换为富文本数据方法,
 * editor:富文本实例, copyLibraryModal:弹窗实例, subtitleHeightratio: y轴的偏移尺度计算量,
 * tts_id: 当前编辑的此项富文本对应的仓库中的唯一id, type:区分全局或者局部
 * } params
 * @returns
 */
export const textImportTorRichtext = async (params) => {
  let {
    data,
    subTitle,
    currentDrawerIndex,
    props,
    sizeData,
    current_tts_data,
    getContent,
    editor,
    copyLibraryModal,
    subtitleHeightratio,
    tts_id,
    type,
  } = params;

  console.log(data, "富文本收到data");
  if (!Array.isArray(data) || !data.length) {
    copyLibraryModal.value.closeModal();
    return;
  }
  data = data[0].material_content;
  if (data !== "") {
    data = data.trim();
    if (data.length > 500) {
      message.warning("文案超过500字，系统将随机截取");
    }
    let sub;
    let ttsData;
    if (type == "Global") {
      // 导入计算x轴 所需要的字体大小
      sub = JSON.parse(
        JSON.stringify(
          subTitle.value.configs.find((ele) => ele.tts_id == props.tts_id)
            .subtitle[0]
        )
      );
      // 基础的 tts配置
      ttsData = JSON.parse(
        JSON.stringify(
          subTitle.value.configs.find((ele) => ele.tts_id == props.tts_id)
        )
      );
    } else {
      // 导入计算x轴 所需要的字体大小
      sub = JSON.parse(
        JSON.stringify(
          subTitle.value[currentDrawerIndex.value.index].tts_config.find(
            (ele) => ele.tts_id == props.tts_id
          ).subtitle[0]
        )
      );
      // 基础的 tts配置
      ttsData = JSON.parse(
        JSON.stringify(
          subTitle.value[currentDrawerIndex.value.index].tts_config.find(
            (ele) => ele.tts_id == props.tts_id
          )
        )
      );
    }

    const font_size = +sub.font_size / scaleData.value.scaleWidth;
    let subTitleArr = splitTextAndRemoveCommas(data.slice(0, 500));
    console.log(subTitleArr, "subTitleArrsubTitleArrsubTitleArr");
    // 切割之后 将切割项 处理成 subtitle数组
    for (let sub_item = 0; sub_item < subTitleArr.length; sub_item++) {
      const textWidth = await getTextWidthUsingCanvas(
        subTitleArr[sub_item],
        font_size,
        sub.font_family
      );
      subTitleArr[sub_item] = {
        ...JSON.parse(JSON.stringify(sub)),
        text: subTitleArr[sub_item],
        ssml: "<speak>" + subTitleArr[sub_item] + "</speak>",
        subtitle_id: nanoid(),
        x: sub.showX - textWidth / 2,
        y: sizeData.value.draggableHeight / subtitleHeightratio,
        material_path: "",
        audio_url: "",
        duration: "",
      };
    }

    current_tts_data.value.subtitle = subTitleArr;
    // 先直接push, 后面过滤一下空的项
    let ssmlContent = subTitleArr
      .map(
        (ele) =>
          `<speak subId="${ele.subtitle_id}" tts_id="${tts_id}">${ele.text}</speak>`
      )
      .join("");
    current_tts_data.value.ssmlContent = ssmlContent;

    nextTick(() => {
      const content = getContent();
      editor.value.commands.setContent(content);
    });

    console.log(
      current_tts_data.value.subtitle,
      " resource_data.value[currentDrawerIndex.value].tts_config"
    );
  }
  copyLibraryModal.value && copyLibraryModal.value.closeModal();
};

/**
 * 处理标题导入
 * @param {
 *  data:文案库选择的数据, state: 抽屉中的缓存数据,
 * activeTextarea:当前编辑的标题文本框的id, copyLibraryModal:弹窗实例,
 * currentDrawerIndex:当前编辑的富文本项下标, type:区分全局或局部
 * }
 */

export const textImportToTitle = (params) => {
  let {
    data,
    state,
    activeTextarea,
    copyLibraryModal,
    currentDrawerIndex,
    type,
  } = params;

  if (!Array.isArray(data) || !data.length) {
    copyLibraryModal.value && copyLibraryModal.value.closeModal();
    return;
  }
  data = {
    text: data[0].material_content,
    id: data[0].id,
  };

  let findTarget;
  if (type == "Global") {
    findTarget = state.value.find((ele) => ele.id == activeTextarea.value);
  } else {
    findTarget = state.value[currentDrawerIndex.value].text_config.find(
      (ele) => ele.id == activeTextarea.value
    );
  }
  findTarget.text_material_id = data.id;
  if (!!findTarget) {
    findTarget.text = data.text.slice(0, 500);
    nextTick(() => {
      const textareaDom = document.querySelector(
        `[data-textareaId="${activeTextarea.value}"]`
      );
      textareaDom.style.height = "auto";
      textareaDom.style.height = `${textareaDom.scrollHeight}px`;
    });
    copyLibraryModal.value && copyLibraryModal.value.closeModal();
  }
};

/**
 * 文案库批量选择 + 导入文本
 * @param {
 * data:导入的列表数据, xLocation比例计算参数, dataSeparation: 组件中的计算属性(所有文本类型的字幕数据)
 * scaleData:缩放数据, splitTextAndRemoveCommas:标点切割方法, key: 列表取文本项的key值
 * } params
 * @returns
 */
export const importListToRichtext = (params) => {
  let {
    data,
    sizeData,
    xLocation,
    dataSeparation,
    // scaleData,
    getTextWidthUsingCanvas,
    subtitleHeightratio,
    key,
  } = params;
  // 固定在中心的点
  const showX = sizeData.value.draggableWidth / xLocation;
  const tts = JSON.parse(
    JSON.stringify(dataSeparation.value.tts_config_text[0])
  );
  const sub = tts.subtitle[0];

  // dataSeparation.value.tts_config_text
  if (scaleData.value.scaleWidth == NaN) {
    alert("nan啦!");
    console.log(scaleData.value);
  }
  console.log(scaleData.value, "scaleDatascaleDatascaleDatascaleData");

  let result = data.map((ele) => {
    const font_size = +sub.font_size / scaleData.value.scaleWidth;

    // 标点切割
    const subTitleArr = splitTextAndRemoveCommas(ele[key]);

    let subArr = subTitleArr.map((item) => {
      const textWidth = getTextWidthUsingCanvas(
        item,
        font_size,
        sub.font_family
      );
      return {
        ...JSON.parse(JSON.stringify(sub)),
        text: item,
        ssml: "<speak>" + item + "</speak>",
        subtitle_id: nanoid(),
        showX,
        x: showX - textWidth / 2,
        y: sizeData.value.draggableHeight / subtitleHeightratio,
        material_path: "",
        audio_url: "",
        duration: "",
      };
    });

    const tts_id = nanoid();
    return {
      ...JSON.parse(JSON.stringify(tts)),
      tab_id: "text",
      tts_id,
      audio_url: "",
      subtitle: [...subArr],
      ssmlContent: subArr
        .map(
          (ele) =>
            `<speak subId="${ele.subtitle_id}" tts_id="${tts_id}">${ele.text}</speak>`
        )
        .join(""),
    };
  });

  console.log(
    [...result, ...dataSeparation.value.tts_config_audio],
    "处理完成后的 富文本数据"
  );
  return result;
};

/**
 * 文案库导入数据到左侧视频组
 *  * @param {
 * data:导入的列表数据, xLocation比例计算参数, dataSeparation: 组件中的计算属性(所有文本类型的字幕数据)
 * scaleData:缩放数据, subtitleHeightratio:y轴的偏移尺度, key: 列表取文本项的key值
 * } params
 */
export const importListToRichtext_subtitle = (paraps) => {
  const {
    data,
    key,
    sizeData,
    xLocation,
    dataSeparation,
    // scaleData,
    subtitleHeightratio,
  } = paraps;

  const showX = sizeData.value.draggableWidth / xLocation;
  const tts = JSON.parse(
    JSON.stringify(dataSeparation.value.tts_config_text[0])
  );
  const sub = tts.subtitle[0];

  // dataSeparation.value.tts_config_text
  let result = data.map((ele) => {
    const font_size = +sub.font_size / scaleData.value.scaleWidth;

    // 标点切割
    const subTitleArr = splitTextAndRemoveCommas(ele[key]);

    let subArr = subTitleArr.map((item) => {
      const textWidth = getTextWidthUsingCanvas(
        item,
        font_size,
        sub.font_family
      );
      return {
        ...JSON.parse(JSON.stringify(sub)),
        text: item,
        ssml: "<speak>" + item + "</speak>",
        subtitle_id: nanoid(),
        showX,
        x: showX - textWidth / 2,
        rightX: showX - textWidth / 2 + textWidth,
        y: sizeData.value.draggableHeight / subtitleHeightratio,
        material_path: "",
        audio_url: "",
        duration: "",
      };
    });

    const tts_id = nanoid();
    return {
      ...JSON.parse(JSON.stringify(tts)),
      tab_id: "text",
      tts_id,
      audio_url: "",
      subtitle: [...subArr],
      ssmlContent: subArr
        .map(
          (ele) =>
            `<speak subId="${ele.subtitle_id}" tts_id="${tts_id}">${ele.text}</speak>`
        )
        .join(""),
    };
  });

  return result;
};

const replaceTitles = [
  "```",
  "- ",
  "-",
  "'''",
  '"""',
  "---",
  "---",
  "-标题：",
  "-标题:",
  "- 标题：",
  "- 标题:",
  "标题:",
  "标题：",
];

const replaceSubTitles = [
  "```",
  "- ",
  "-",
  "'''",
  '"""',
  "---",
  "---",
  "-副标题：",
  "-副标题:",
  "副标题：",
  "副标题:",
  "- 副标题：",
  "- 副标题:",
];

const replaceContent = [
  "```",
  "- ",
  "-",
  "'''",
  '"""',
  "---",
  "---",
  "-内容：",
  "-内容:",
  "- 内容：",
  "- 内容:",
  "内容：",
  "内容:",
];

// 处理 sse返回的文本信息
export function parseTextToObject(text) {
  // 确保文本被分成行
  const lines = text.trim().split("\n");

  const result = {
    "-标题": "",
    "-副标题": "",
    "-内容": "",
  };

  if (lines?.[1]) {
    replaceTitles.forEach((ele) => {
      lines[1] = lines[1].replace(new RegExp(ele, "g"), "").trim(); // 使用正则表达式
    });
    result["-标题"] = lines[1];
  }
  if (lines?.[2]) {
    replaceSubTitles.forEach((ele) => {
      lines[2] = lines[2].replace(new RegExp(ele, "g"), "").trim(); // 使用正则表达式
    });
    result["-副标题"] = lines[2];
  }
  // if (lines?.[3]) {
  //   replaceContent.forEach((ele) => {
  //     lines[3] = lines[3].replace(new RegExp(ele, "g"), "").trim(); // 使用正则表达式
  //   });
  //   result["-内容"] = lines[3];
  // }

  // 开始处理内容部分
  for (let i = 3; i < lines.length; i++) {
    if (lines[i]) {
      replaceContent.forEach((ele) => {
        lines[i] = lines[i].replace(new RegExp(ele, "g"), "").trim(); // 使用正则表达式
      });
      result["-内容"] += (result["-内容"] !== "" ? "\n" : "") + lines[i];
    }
  }

  // 如果没有额外的内容行，则尝试设置第三行为内容（如果存在）
  if (!result["-内容"] && lines?.[3]) {
    replaceContent.forEach((ele) => {
      lines[3] = lines[3].replace(new RegExp(ele, "g"), "").trim(); // 使用正则表达式
    });
    result["-内容"] = lines[3];
  }

  return result;
}

/**
 * 截取视频的帧, 生成canvas并返回图片地址
 * @param {string} videoUrl: 视频链接
 * @returns {Promise<string>} 截取的图片地址
 */
export const captureFirstFrame = async (videoUrl) => {
  return new Promise((resolve, reject) => {
    const videoElement = document.createElement("video"); // 创建视频元素
    videoElement.crossOrigin = "anonymous"; // 设置跨域属性

    videoElement.src = videoUrl + "?v=" + new Date().valueOf(); // 赋值视频链接

    // 等待视频元数据加载完成
    videoElement.addEventListener(
      "loadedmetadata",
      async () => {
        const videoDuration = videoElement.duration; // 获取视频时长
        const captureTime = videoDuration * 0.1; // 计算截取时间为视频时长的10%
        // 获取视频的实际宽高
        const videoWidth = videoElement.videoWidth;
        const videoHeight = videoElement.videoHeight;

        // 设置视频的当前播放时间
        videoElement.currentTime = captureTime;

        // 等待视频跳转到该时间点
        videoElement.addEventListener(
          "seeked",
          () => {
            const canvasElement = document.createElement("canvas");
            const ctx = canvasElement.getContext("2d");

            const scale = videoWidth || videoHeight > 720 ? 0.6 : 1;

            // 设置canvas的大小缩放
            // * 0.7
            canvasElement.width = videoWidth * scale;
            canvasElement.height = videoHeight * scale;

            // 绘制当前视频帧到canvas上
            ctx.drawImage(
              videoElement,
              0,
              0,
              canvasElement.width,
              canvasElement.height
            );

            // 将当前帧转换为base64编码的图片
            const base64ImageData = canvasElement.toDataURL("image/jpeg", 1);
            resolve(base64ImageData); // 返回图片地址
          },
          { once: true }
        );
      },
      { once: true }
    );

    // 错误处理
    videoElement.addEventListener("error", (error) => {
      reject(error);
    });
  });
};

// 判断某个视频组中 有没有文字
export const hasText = (params) => {
  const { targetData } = params;

  let isNotEmpty = false;
  // 当前编辑的项
  if (targetData.tab_id == "text") {
    const text_tts_config = targetData.tts_config.filter(
      (ele) => ele.tab_id == "text"
    );
    isNotEmpty = text_tts_config.some((ele) => {
      return ele.subtitle.some(
        (i) => !!i.text.trim() && i.text.trim() !== "\n"
      );
    });
  } else if (targetData.tab_id == "audio") {
    const audio_tts_config = targetData.tts_config.filter(
      (ele) => ele.tab_id == "audio"
    );
    isNotEmpty = audio_tts_config.some((ele) => {
      return ele.subtitle.some(
        (i) => !!i.text.trim() && i.text.trim() !== "\n"
      );
    });
  }
  return isNotEmpty;
};

// 判断某个镜头组是否有音频
export const hasVideo = (params) => {
  const { targetData, VideoMashup, isNotEmpty } = params;
  // 开启了全局字幕配音, 不允许选择音频选项
  if (VideoMashup.value?.global_tts_config?.type == 1) {
    return {
      disabled: true,
      msg: "开启全局字幕配音无法选择此项",
    };
  }
  if (targetData.tab_id == "text") {
    // 开启音频才算有音频
    let activeItem = targetData.tts_config.filter(
      (ele) => ele.tab_id == "text"
    );
    // 是否有一项 不包含音频
    // const haveAudio = activeItem.some((ele) => !ele.audio_url);
    const haveAudio = activeItem.some((ele) =>
      ele.subtitle.some((i) => !i.audio_url)
    );
    if (
      activeItem[0].showVoice == false ||
      isNotEmpty.value == false ||
      haveAudio
    ) {
      return {
        disabled: true,
        msg: "镜头组无音频，无法选择",
      };
    } else {
      return {
        disabled: false,
        msg: "",
      };
    }
  } else if (targetData.tab_id == "audio") {
    let activeItems = targetData.tts_config.filter(
      (ele) => ele.tab_id == "audio"
    );
    let disable = activeItems.some((ele) => {
      return ele.audio_url == "";
    });
    return {
      disabled: disable,
      msg: disable ? "镜头组无音频，无法选择" : "",
    };
  }
};

/**
 *
 * @param {需要分组的数组} array
 * @param {每一组的分组数量} chunkSize
 * @returns 返回分组之后的数组
 */
export const chunkArray = (array, chunkSize) => {
  const result = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    const chunk = array.slice(i, i + chunkSize);
    result.push(chunk);
  }
  return result;
};

// 获取所有视频组中的, 每个tts的每个subtitle的音频
export const getAllTemplateAudio = async (templateList) => {
  console.log(templateList, "接收到即将获取音频的数据乐乐乐乐乐");
  const promiseArr = [];
  const ttsArr = [];
  templateList.forEach((ele) => {
    const target_tts = ele.tts_config.filter((i) => i.tab_id == "text");
    if (target_tts.length) {
      // 有tts项, 需要获取音频
      // 获取音频
      target_tts.forEach((item) => {
        promiseArr.push(() =>
          getItemTts_subtitle_audioData(item, {
            mexid_all: false,
          })
        );
      });
    }
  });

  // return;
  console.log(ttsArr, "ttsArr");

  // return;
  console.log("promiseArr", promiseArr);

  const ttsChunkArr = chunkArray(promiseArr, chunkNum);
  console.log("异步获取音频数组", ttsChunkArr);
  return new Promise(async (resolve, reject) => {
    message.loading("字幕语音转换中...", 0);
    try {
      // await new Promise(async(resolve, reject) => {
      for (let i = 0; i < ttsChunkArr.length; i++) {
        await Promise.all(ttsChunkArr[i].map((ele) => ele()))
          .then(() => {
            console.log("完成了一组视频组的音频获取");
          })
          .catch((err) => {
            console.log("视频组音频获取失败");
            reject(err);
            throw new Error(err);
          });
      }
      // });

      message.destroy();
      resolve(templateList);
    } catch (error) {
      message.destroy();
      reject(error);
    }
  });
};

// 获取单项的tts音频
export const getItemTts_subtitle_audioData = (tts_item, params) => {
  return new Promise(async (resolve, reject) => {
    const { mexid_all } = params;
    // 只取没有音频的项, 获取音频
    // const textAndSubtitleId = tts_item.flatMap((ele) =>
    const textAndSubtitleId = tts_item.subtitle
      .filter(
        (sub) => !!sub.text.trim() && sub.text.trim() !== "\n" && !sub.audio_url
      )
      .map((sub) => ({ text: sub.ssml, id: sub.subtitle_id }));
    // );
    if (Array.isArray(textAndSubtitleId) && textAndSubtitleId.length >= 1) {
      // console.log(textAndSubtitleId, ssml_content, '每一项的数据');
      // 有需要获取音频的选项 - 取第一个公共参数作为基础配置

      // 异步数组
      let promiseList = [];

      // 循环中 处理每一组数据, 将subtitle 扁平数组 处理成 嵌套数组 每一个嵌套数组处理成一个请求项
      const subChunkArr = chunkArray(textAndSubtitleId, chunkNum);

      // 获取音频的异步方法
      const promiseItem = (data) => {
        const { requestData } = data;
        return new Promise(async (resolve, reject) => {
          // 获取此项 tts的音频选项
          // console.log(requestData, "每一组的每一个接受到的参数");
          try {
            const res = await request.post(
              "/work_ai",
              "/user/shotstack/textToVoice/many",
              { ...requestData, mexid_all }
            );
            // console.log(res.result, "many调用的结果");
            if (res?.code && res.code != 1000) {
              throw new Error(res);
            }
            // 创建一个函数用于延迟
            const delay = (ms) =>
              new Promise((timeresolve) => setTimeout(timeresolve, ms));

            // 找到对应的数据, 存放数据
            const setVoice = (arr) => {
              // tts_item.flatMap((sub, index) => {
              tts_item.subtitle.forEach((ele) => {
                const findTarget = arr.find((i) => i.id == ele.subtitle_id);
                if (!!findTarget) {
                  ele.audio_url = findTarget.audio;
                  ele.duration = findTarget.duration * 1000;
                  if(findTarget?.duration_ms && findTarget?.duration_ms > 0){
                    ele.duration = findTarget.duration_ms;
                  } 
                  ele.end_time = ele.duration;
                  ele.media_id = findTarget?.oss_media_id || "";
                  ele.material_path = findTarget?.material_path || "";
                }
              });
            };

            // 使用新的获取音频接口
            const getItemVoice = async () => {
              const itemVoice = await request.get(
                "/work_ai",
                `/user/shotstack/textToVoice/many/result/${requestData.unique}`
              );
              // console.log("单项的轮询结果123", itemVoice);
              if (itemVoice?.code && itemVoice?.code != 1000) {
                throw new Error(itemVoice);
              }
              if (itemVoice?.result?.status) {
                if (itemVoice.result.status == "loading") {
                  await delay(2000);
                  await getItemVoice();
                  return;
                }
                if (itemVoice.result.status == "error") {
                  return message.error("音频获取失败!");
                }
              } else {
                // console.log("itemVoice?.result 有数据啦", itemVoice?.result);
                setVoice(itemVoice?.result);
              }
            };
            await getItemVoice();
          } catch (error) {
            message.destroy();
            nextTick(() => {
              message.error("字幕语音转换失败,请重试!");
            });
            reject();
          }

          console.log('获取了时长---------');
          tts_item.duration = tts_item.subtitle.reduce((pre, cur) => {
            if (!!cur.duration) {
              return pre + Number(cur.duration);
            }
            return pre;
          },0);
          resolve();
        });
      };

      for (let ele of subChunkArr) {
        const {
          speed,
          tone_id,
          volume,
          emotion_category,
          emotion_intensity,
          id,
          category,
          voice_type,
          recommendSpeed,
        } = tts_item;
        const requestData = {
          text: ele,
          speed: voice_type == 2 ? recommendSpeed : speed,
          timbre_id: tone_id,
          volume,
          emotion_category,
          emotion_intensity,
          unique: nanoid(),
          id,
          category,
          // ssml_content
        };
        // 参数传入到异步函数中
        promiseList.push(
          promiseItem({
            requestData,
          })
        );
      }

      // 将所有的请求项处理为 分组函数
      const promiseGrouping = chunkArray(promiseList, chunkNum);
      // await promiseItem({ requestData }); // 每一个异步函数
      for (let i = 0; i < promiseGrouping.length; i++) {
        await Promise.all(promiseGrouping[i])
          .then((res) => {
            console.log("一组成功");
          })
          .catch((err) => {
            console.log(err, "一组失败");
            reject();
          });
      }
      resolve();
    } else {
      resolve();
    }
  });
};

// 批量获取音频, 获取+重试方法
const modelRef = ref(null);
export const getAudioFn = async (params) => {
  const { resource_data } = params;
  console.log(resource_data, '需要获取音频的数据');
  

  return new Promise(async (resolve, reject) => {
    const fn = async () => {
      modelRef.value && modelRef.value.destroy();
      await getAllTemplateAudio(resource_data.value)
        .then(() => {
          resolve();
        })
        .catch(() => {
          modelRef.value = Modal.confirm({
            title: "提示",
            icon: createVNode(ExclamationCircleOutlined),
            content: "是否尝试重新获取音频数据？",
            okText: "确认",
            cancelText: "取消",
            zIndex:1003,
            onOk: async () => {
              await fn();
            },
            onCancel: async() => {
              try {
                await clearEmptySubtitleModal({resource_data})
                reject();
                modelRef.value.destroy();
                throw new Error("取消");
              } finally {

              }
            }
          });
        });
    };

    await fn();
  });
};

const clearEmptySubtitleRef = ref()
// 取消重新获取音频, 清空所有没有成功获取音频的项
const clearEmptySubtitleModal = (params) => {
  const { resource_data } = params;
  return new Promise((resolve, rej) => {
    clearEmptySubtitleRef.value = Modal.confirm({
      title: "提示",
      icon: createVNode(ExclamationCircleOutlined),
      content: "即将清空所有音频获取失败的文案",
      okText: "确认",
      cancelText: '取消',
      zIndex:1004,
      onOk: () => {
        clearEmptySubtitle({resource_data})
        resolve()
      },
      onCancel:  () => {
        clearEmptySubtitleRef.value.destroy();
        rej()
      },

    });
  })
}

// 清空所有 没有音频的subtitle
const clearEmptySubtitle = (params) => {
  
  const { resource_data } = params;
  resource_data.value.forEach((ele) => {
    const target_tts = ele.tts_config.filter((i) => i.tab_id == "text");
    if (target_tts.length) {
      // 有tts项, 需要获取音频
      // 获取音频
      target_tts.forEach((item) => {
          item.subtitle = item.subtitle.filter(
            (sub) => !!sub.text.trim() && sub.text.trim() !== "\n" && sub.audio_url
          )

        // 如果筛选之后 没有数据呢, 则添加一项基础数据
        if (!item.subtitle.length) {
          item.subtitle = [baseSubtitle()]
        }
        // 配置ssml内容
        item.ssmlContent = item.subtitle.map(ele => {
          return `<speak subid="${ele.subtitle_id}" tts_id="${item.tts_id}"></speak>`;
        }).join('')
      });
    }
  });
}

/**
 *
 * @param {tts_ids: tts项的id, allVoiceData:全部的音色数组, duplicate:是否去重} param
 * @returns
 */
export const getRandomVoice = (
  param = { tts_ids: [], allVoiceData: [], duplicate: true }
) => {
  const { tts_ids, allVoiceData, duplicate } = param;
  // debugger
  const len = allVoiceData.length;
  const randomVoice = {};
  // debugger;

  return new Promise(async (res, rej) => {
    if (tts_ids.length == allVoiceData.length) {
      tts_ids.forEach((ele, index) => {
        randomVoice[ele] = allVoiceData[index];
      });
      return res(randomVoice);
    }

    let haveIndex = [];
    for (let key of tts_ids) {
      // 获取随机下标
      const random = () => {
        return Math.floor(Math.random() * len);
      };
      const fn = () => {
        return new Promise((resolve, reject) => {
          // 获取去重的随机下标
          const getRandom = () => {
            const index = random();
            // 开启去重(需要保证)
            if (duplicate && len > tts_ids.length) {
              if (haveIndex.includes(index)) {
                getRandom();
                return;
              } else {
                haveIndex.push(index);
                randomVoice[key] = allVoiceData[index];
                resolve(index);
              }
            } else {
              haveIndex.push(index);
              randomVoice[key] = allVoiceData[index];
              resolve(index);
            }
          };
          getRandom();
        });
      };
      await fn();
    }

    console.log(randomVoice, "随机的音色值");
    res(randomVoice);
  });
};

// 获取小圆点试听的某项 音色, 需要对tts去重
export const getRandomItemVoice = (params) => {
  const { tts_arr, allVoiceData } = params;
  return new Promise((resolve, reject) => {
    let index;
    let findIndexArr = [];
    tts_arr.forEach((ele) => {
      const findIndex = allVoiceData.findIndex(
        (i) => i.timbre_id == ele.tone_id
      );
      findIndex != -1 && findIndexArr.push(findIndex);
    });
    // debugger;
    const fn = () => {
      // return new Promise((resolve, reject) => {
      index = Math.floor(Math.random() * allVoiceData.length);
      if (findIndexArr.includes(index)) {
        fn();
      } else {
        resolve(allVoiceData[index]);
      }
      // });
    };

    fn();
  });
};

/**
 * @param {haveAudio:是否过滤掉包含音频的项, data:视频组信息}
 * @returns 获取视频组中所有的字符(用于积分消耗评估)
 */
export const getAllText = (config={}) => {
  const {haveAudio=true, data} = config;
  return new Promise((resolve, reject) => {
    if (haveAudio) {
      try {
              const str = data
        .flatMap(item => item.tts_config) // 将所有 tts_config 展开
        .filter(config => config.tab_id === "text") // 过滤 tab_id 为 "text" 的项
        .flatMap(config => config.subtitle) // 获取 subtitle 数组
        .filter(subtitle => subtitle.audio_url === "") // 过滤 audio_url 为空的项
        .map(subtitle => subtitle.text) // 提取 text 字段
        .join(""); // 拼接成一个字符串
      resolve(str)
      } catch (error) {
        console.log(error, '获取文字失败');
        reject(error)
      }
    }
  });
}

//  转换毫秒为时分秒
export const millisToHoursMinutesSeconds = (millis) => {
  let seconds = Math.floor(millis / 1000);
  let minutes = Math.floor(seconds / 60);
  let hours = Math.floor(minutes / 60);

  seconds = seconds % 60;
  minutes = minutes % 60;

  // 使用padStart来确保数字至少为两位数，不足补0
  hours = hours.toString().padStart(2, "0");
  minutes = minutes.toString().padStart(2, "0");
  seconds = seconds.toString().padStart(2, "0");
  return `${hours}:${minutes}:${seconds}`;
};

// 测量元素填充文字之后的宽度
export const measureTextWithSpan = (element, text) => {
  // 创建一个临时的 span 元素
  // debugger
  const tempSpan = document.createElement("p");
  // visibility: hidden;
  tempSpan.style.cssText = `
    position: absolute;
    white-space: pre-wrap;
    font-size: ${getComputedStyle(element)["font-size"]};
    font-style: ${getComputedStyle(element)["font-style"]};
    font-weight: ${getComputedStyle(element)["font-weight"]};
    line-height: ${getComputedStyle(element)["line-height"]};
    font-family: ${getComputedStyle(element)["font-family"]};
    word-wrap: ${getComputedStyle(element)["word-wrap"]};
    word-break: ${getComputedStyle(element).wordBreak};
    text-align: ${getComputedStyle(element).textAlign};
    padding:${getComputedStyle(element).padding};
  `;
  tempSpan.textContent = text;

  // 将 span 添加到 body 中以便计算样式
  document.body.appendChild(tempSpan);

  // 获取 span 的宽度和高度
  // 补充误差
  const width = tempSpan.offsetWidth + 3;
  const height = tempSpan.offsetHeight;
  // 移除 span
  document.body.removeChild(tempSpan);

  return { width, height };
};

export const tool = {
  //  转换毫秒为时分秒
  millisToHoursMinutesSeconds,
  measureTextWithSpan
}